<template>
  <div class="dashboard-page">
    <div class="dashboard-grid">
      <div class="card hero-card">
        <div class="hero-content">
          <div class="hero-header">
            <div class="hero-label">本周碳排放</div>
            <div class="hero-value"><span class="num">{{ weeklyTotal }}</span><span class="unit">kg</span></div>
            <div class="hero-change"><ArrowDown class="icon" /><span>较上周下降 15%</span></div>
          </div>
          <div class="hero-footer">
            <div class="progress-labels">
              <span class="progress-text">本周目标已用完成{{ goalPercent }}%</span>
              <span class="goal-text">目标 {{ weeklyGoal }}kg</span>
            </div>
            <div class="progress-track">
              <div class="progress-fill" :style="{ width: goalPercent + '%' }"></div>
            </div>
          </div>
        </div>
      </div>

      <div class="card quick-card">
        <div class="card-header">快速记录</div>
        <div class="quick-form">
          <input v-model="quickText" ref="quickInputRef" type="text" placeholder="例如：地铁 5km 或 牛肉 0.35kg" @keyup.enter="submitQuickText" />
          <select v-model="selectedCategory">
            <option value="">自动识别</option>
            <option value="餐饮">餐饮</option>
            <option value="交通">交通</option>
            <option value="购物">购物</option>
            <option value="能源">能源</option>
          </select>
          <button class="primary-btn" @click="submitQuickText">记录</button>
        </div>
        <div class="quick-chips">
          <button class="chip" @click="applyQuickChip('牛肉 0.35kg')">牛肉 0.35kg</button>
          <button class="chip" @click="applyQuickChip('地铁 5km')">地铁 5km</button>
          <button class="chip" @click="applyQuickChip('公交 10km')">公交 10km</button>
          <button class="chip" @click="applyQuickChip('电费 8kWh')">电费 8kWh</button>
        </div>
      </div>

      <div class="card breakdown-card">
        <div class="card-header">本周碳排构成</div>
        <div class="composition">
          <div class="donut">
            <div class="donut-ring" :style="donutStyle">
              <div class="donut-center">
                <div class="donut-total">{{ weeklyTotal }}kg</div>
                <div class="donut-label">本周总计</div>
              </div>
            </div>
          </div>
          <div class="comp-list">
            <div class="comp-item" v-for="g in sortedBreakdown" :key="displayCategoryName(g)">
              <div class="comp-left">
                <span class="comp-dot" :style="{ backgroundColor: categoryColorMap[displayCategoryName(g)] || '#10b981' }"></span>
                <span class="comp-name">{{ displayCategoryName(g) }}</span>
              </div>
              <div class="comp-right">
                <span class="comp-percent">{{ percentOf(g) }}%</span>
                <span class="comp-value">{{ g.carbon_emission }}kg</span>
              </div>
            </div>
          </div>
        </div>
      </div>

      <div class="card history-card">
        <div class="card-header">
          <span>历史记录</span>
          <a class="view-all" href="javascript:void(0)">查看全部</a>
        </div>
        <div class="history-body">
          <div v-if="!todayRecorded" class="today-tip">今日未记录</div>
          <div class="history-item" v-for="item in recentHistory" :key="item.footprint_id">
            <span class="date">{{ item.record_date }}</span>
            <div class="history-main">
              <span class="dot" :style="{ backgroundColor: categoryPalette[displayCategoryRaw(item.category)] || '#6b7280' }"></span>
              <span class="desc">{{ item.description || displayCategoryRaw(item.category) }}</span>
            </div>
            <span class="value">{{ item.carbon_emission }}kg</span>
          </div>
        </div>
      </div>

      <div class="card trend-card">
        <div class="card-header">
          <span>最近趋势</span>
          <div class="header-tools">
            <button class="tool-btn" :class="{ active: selectedDays===7 }" @click="setDays(7)">7天</button>
            <button class="tool-btn" :class="{ active: selectedDays===30 }" @click="setDays(30)">30天</button>
          </div>
        </div>
        <div class="chart-area">
          <div v-if="trendLoading" class="chart-skeleton"></div>
          <div v-else ref="trendChartRef" class="trend-chart"></div>
        </div>
      </div>

      <div class="card tips-card">
        <div class="card-header">
          <span>低碳小贴士</span>
          <button class="swap-btn" @click="refreshKnowledge" :disabled="loadingKnowledge"><RefreshCw class="swap-icon" />换一批</button>
        </div>
        <div class="tips-grid">
          <div v-if="loadingKnowledge" class="tips-skeleton"></div>
          <template v-else>
            <div v-if="knowledgeError" class="knowledge-error">
              {{ knowledgeError }}
              <button class="retry-btn" @click="fetchKnowledge">重试</button>
            </div>
            <div class="tip-item" v-for="(k, idx) in tipsData" :key="(k.title||'') + '-' + idx">
              <div class="tip-icon-wrap"><Lightbulb class="tip-icon" /></div>
              <div class="tip-content">
                <div class="tip-title">{{ k.title }}</div>
                <div class="tip-desc">{{ k.description || k.summary }}</div>
                <div v-if="k.potentialSaving || k.expectedReductionKg" class="tip-saving">{{ k.potentialSaving || ('约可减少 ' + k.expectedReductionKg + 'kg/周') }}</div>
              </div>
            </div>
          </template>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, computed, watch, nextTick } from 'vue'
import * as echarts from 'echarts'
import { ArrowDown, Utensils, Car, ShoppingBag, Zap, Lightbulb, RefreshCw, Circle } from 'lucide-vue-next'
import { listFootprints, createFootprint, getStatistics, getTrend, getRecommendations, getKnowledgeFeed } from '../api/carbon'

const weeklyTotal = ref('0.00')
const weeklyByCategory = ref<any[]>([])
const recentHistory = ref<any[]>([])
const selectedDays = ref(30)
const suggestions = ref<any[]>([])
const knowledgeItems = ref<any[]>([])
const loadingKnowledge = ref(false)
const knowledgeError = ref('')
const quickText = ref('')
const selectedCategory = ref('')
const quickInputRef = ref<HTMLInputElement|null>(null)
const todayRecorded = ref(false)

const categoryPalette: Record<string,string> = {
  '餐饮': '#10b981',
  '交通': '#3b82f6',
  '购物': '#a855f7',
  '能源': '#f59e0b',
  '未分类': '#6b7280',
  '其他': '#6b7280'
}
const displayCategoryName = (g: any) => {
  const name = String(g?.category || '')
  if (name === '未分类') return '其他'
  return name
}
const displayCategoryRaw = (name: string) => {
  if (name === '未分类') return '其他'
  return name || '记录'
}
const categoryIcon = (cat: string) => {
  if (cat.includes('餐')) return Utensils
  if (cat.includes('交')) return Car
  if (cat.includes('购')) return ShoppingBag
  if (cat.includes('能')) return Zap
  if (cat.includes('其')) return Circle
  return Utensils
}
const categoryColorMap = computed<Record<string,string>>(() => {
  const m: Record<string,string> = {}
  weeklyByCategory.value.forEach((g: any, i: number) => {
    const keyRaw = String(g?.category ?? `C${i}`)
    const key = keyRaw === '未分类' ? '其他' : keyRaw
    m[key] = categoryPalette[key] || ['#10b981','#3b82f6','#a855f7','#f59e0b'][i % 4]
  })
  return m
})
const breakdownPercent = (g: any) => {
  const max = Math.max(...weeklyByCategory.value.map(x => Number(x.carbon_emission || 0)), 1)
  const v = Number(g.carbon_emission || 0)
  return Math.round(v / max * 100)
}

const weeklyGoal = ref(10)
const goalPercent = computed(() => {
  const t = Number(weeklyTotal.value || 0)
  const goal = Number(weeklyGoal.value || 0) || 1
  return Math.min(100, Math.round(t / goal * 100))
})
const barColor = computed(() => goalPercent.value >= 95 ? '#f59e0b' : '#10b981')
const breakdownTotal = computed(() => weeklyByCategory.value.reduce((s, g) => s + Number(g.carbon_emission || 0), 0))
const sortedBreakdown = computed(() => {
  const arr = weeklyByCategory.value.filter((g: any) => Number(g.carbon_emission || 0) > 0)
  return arr.sort((a,b) => Number(b.carbon_emission || 0) - Number(a.carbon_emission || 0))
})
const percentOf = (g: any) => breakdownTotal.value ? Math.round(Number(g.carbon_emission || 0) / breakdownTotal.value * 100) : 0
const donutStyle = computed(() => {
  const total = breakdownTotal.value
  if (!total) return { background: 'conic-gradient(#e5e7eb 0 100%)' }
  let acc = 0
  const parts = sortedBreakdown.value.map((g: any, i: number) => {
    const p = Number(g.carbon_emission || 0) / total * 100
    const start = acc
    acc += p
    const key = displayCategoryName(g)
    const color = categoryColorMap.value ? (categoryColorMap.value[key] || '#10b981') : '#10b981'
    return `${color} ${start}% ${acc}%`
  })
  return { background: `conic-gradient(${parts.join(',')})` }
})

const submitQuickText = async () => {
  const text = (quickText.value || '').trim()
  if (!text) return
  try {
    const payload: any = { text }
    if (selectedCategory.value) payload.category = selectedCategory.value
    await createFootprint(payload)
    quickText.value = ''
    selectedCategory.value = ''
    await fetchAll()
  } catch (e: any) {
    const msg = e?.response?.data?.message || '记录失败'
    showMessage(msg,'error')
  }
}
const applyQuickChip = async (text: string) => {
  quickText.value = text
  await submitQuickText()
}

const showMessage = (message: string, type: 'success' | 'error' = 'success') => {
  const toast = document.createElement('div')
  toast.textContent = message
  const base = 'position:fixed;left:50%;bottom:80px;transform:translateX(-50%);padding:10px 16px;border-radius:10px;color:#fff;box-shadow:0 6px 20px rgba(0,0,0,0.25);z-index:9999;font-size:14px;opacity:0.95;'
  const bg = type === 'success' ? 'background:#2E8B57;' : 'background:#E74C3C;'
  toast.setAttribute('style', base + bg)
  document.body.appendChild(toast)
  setTimeout(() => {
    toast.style.transition = 'opacity 0.3s ease'
    toast.style.opacity = '0'
    setTimeout(() => { toast.remove() }, 300)
  }, 1800)
}

const fetchWeekly = async () => {
  const end = new Date()
  const start = new Date(end.getTime() - 6 * 24 * 3600 * 1000)
  const fmt = (d: Date) => `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`
  const resp: any = await getStatistics({ start_date: fmt(start), end_date: fmt(end), group_by: 'category' })
  if (resp.success) {
    const raw = resp.data.by_category || []
    const acc: Record<string, number> = {}
    raw.forEach((g: any) => {
      const name = displayCategoryName(g)
      const v = Number(g.carbon_emission || 0)
      acc[name] = (acc[name] || 0) + v
    })
    if (acc['能源'] === undefined) acc['能源'] = 0
    const order = ['餐饮','交通','购物','能源','其他']
    const list: any[] = []
    order.forEach(k => {
      if (k === '其他') {
        if (acc[k] && acc[k] > 0) list.push({ category: k, carbon_emission: acc[k] })
      } else {
        list.push({ category: k, carbon_emission: acc[k] || 0 })
      }
    })
    weeklyByCategory.value = list
    const total = resp.data.total || '0'
    weeklyTotal.value = total
  }
}

const fetchHistory = async () => {
  const resp: any = await listFootprints({ page_size: 5 })
  if (resp.success) {
    recentHistory.value = (resp.data.items || [])
  }
}

const fetchTodayStatus = async () => {
  const d = new Date()
  const fmt = (x: Date) => `${x.getFullYear()}-${String(x.getMonth()+1).padStart(2,'0')}-${String(x.getDate()).padStart(2,'0')}`
  const today = fmt(d)
  const resp: any = await listFootprints({ start_date: today, end_date: today, page_size: 1 })
  todayRecorded.value = !!(resp.success && (resp.data.items || []).length)
}

const trendLoading = ref(false)
const trendChartRef = ref<HTMLDivElement|null>(null)
let trendChart: echarts.ECharts | null = null
const trendDates = ref<string[]>([])
const trendUser = ref<number[]>([])
const trendCity = ref<number[]>([])
const hasCity = computed(() => (trendCity.value || []).some(v => v != null))
const renderTrend = () => {
  if (!trendChartRef.value) return
  if (!trendChart) trendChart = echarts.init(trendChartRef.value)
  const dates = trendDates.value
  const user = trendUser.value
  const city = trendCity.value
  const option: echarts.EChartsOption = {
    grid: { left: 12, right: 12, top: 24, bottom: 24 },
    xAxis: { type: 'category', data: dates, axisLine: { lineStyle: { color: '#e5e7eb' } }, axisTick: { show: false } },
    yAxis: { type: 'value', axisLine: { show: false }, splitLine: { lineStyle: { type: 'dashed', color: '#e5e7eb' } } },
    tooltip: { trigger: 'axis', backgroundColor: '#fff', borderColor: '#e5e7eb', borderWidth: 1, textStyle: { color: '#111827' } },
    series: [
      { type: 'line', name: '我的', data: user, smooth: true, symbolSize: 6, lineStyle: { color: '#10b981' }, areaStyle: { color: 'rgba(16,185,129,0.2)' } },
      ...(hasCity.value ? [{ type: 'line' as const, name: '同城', data: city, smooth: true, symbolSize: 6, lineStyle: { color: '#f59e0b' }, areaStyle: { color: 'rgba(245,158,11,0.12)' } }] : [])
    ]
  }
  trendChart.setOption(option)
}
const fetchTrend = async () => {
  if (trendChart) {
    trendChart.dispose()
    trendChart = null
  }
  trendLoading.value = true
  const resp: any = await getTrend({ days: selectedDays.value })
  if (resp.success) {
    trendDates.value = (resp.data.dates || []).map((d: string) => d.slice(5))
    trendUser.value = (resp.data.user_emission || []).map((x: any) => Number(x || 0))
    trendCity.value = (resp.data.city_average_emission || []).map((x: any) => Number(x || 0))
  }
  trendLoading.value = false
  await nextTick()
  renderTrend()
}

const setDays = async (d: number) => {
  selectedDays.value = d
  await fetchTrend()
}

const tipsData = computed(() => {
  return (knowledgeItems.value && knowledgeItems.value.length) ? knowledgeItems.value : suggestions.value
})

const fetchSuggestions = async () => {
  const resp: any = await getRecommendations({ horizon_days: 7 })
  if (resp.success) {
    suggestions.value = resp.data.items || []
  }
}

const mockTips = [
  { id: 't1', title: '使用公共交通', description: '工作日尽量公交或地铁出行，每周可减少约 1.2kg', potentialSaving: '约可减少 1.2kg/周' },
  { id: 't2', title: '低碳饮食', description: '减少红肉摄入，增加蔬果，每周可减少约 0.8kg', potentialSaving: '约可减少 0.8kg/周' },
  { id: 't3', title: '节能用电', description: '更换节能灯泡，关闭待机设备，每周可减少约 0.5kg', potentialSaving: '约可减少 0.5kg/周' }
]
const fetchKnowledge = async () => {
  loadingKnowledge.value = true
  knowledgeError.value = ''
  try {
    const resp: any = await getKnowledgeFeed({ horizon_days: 7 })
    if (resp.success) {
      let arr = Array.isArray(resp?.data?.items) ? resp.data.items : []
      if (!arr.length) {
        const resp2: any = await getKnowledgeFeed({ horizon_days: 7, force: 'true' as any })
        if (resp2.success) {
          arr = Array.isArray(resp2?.data?.items) ? resp2.data.items : []
        } else {
          knowledgeError.value = String(resp2.message || '加载失败')
        }
      }
      knowledgeItems.value = arr.map((x: any) => ({ ...x }))
    } else {
      knowledgeError.value = String(resp.message || '加载失败')
    }
  } catch (e: any) {
    console.error('[知识补给站] 加载失败', e)
    const msg = String(e?.message || '')
    if (msg.toLowerCase().includes('timeout')) {
      knowledgeError.value = '请求超时，已显示默认建议'
      knowledgeItems.value = mockTips
    } else {
      knowledgeError.value = String(e?.message || '网络错误')
    }
  }
  loadingKnowledge.value = false
}

let refreshTimer: any = null
const refreshKnowledge = async () => {
  if (refreshTimer) clearTimeout(refreshTimer)
  refreshTimer = setTimeout(async () => {
    loadingKnowledge.value = true
    knowledgeError.value = ''
    try {
      const resp: any = await getKnowledgeFeed({ horizon_days: selectedDays.value as any, force: 'true' as any })
      if (resp.success) {
        const arr = Array.isArray(resp?.data?.items) ? resp.data.items : []
        knowledgeItems.value = arr.map((x: any) => ({ ...x }))
      } else {
        knowledgeError.value = String(resp.message || '加载失败')
      }
    } catch (e: any) {
      console.error('[知识补给站] 刷新失败', e)
      knowledgeError.value = String(e?.message || '网络错误')
    }
    loadingKnowledge.value = false
  }, 400)
}

const fetchAll = async () => {
  await Promise.all([fetchWeekly(), fetchHistory(), fetchTodayStatus(), fetchTrend(), fetchSuggestions(), fetchKnowledge()])
}

onMounted(async () => {
  await fetchAll()
})
</script>

<style scoped>
:root { --emerald-500:#10b981; --amber-500:#f59e0b; --bg:#fafafa; --card:#ffffff; --border:#e5e7eb; --gray-900:#111827; --gray-700:#374151; --gray-600:#6b7280; --gray-500:#6b7280; --gray-400:#9ca3af; }
.dashboard-page { width: 100%; padding: 24px; box-sizing: border-box; background: var(--bg); }
.dashboard-grid { max-width: 1400px; margin: 0 auto; display: grid; grid-template-columns: repeat(3,1fr); gap: 24px; }
.card { background: var(--card); border: 1px solid var(--border); border-radius: 12px; box-shadow: 0 8px 24px rgba(0,0,0,0.06); padding: 24px; }

.hero-card {
  grid-column: span 2;
  background: linear-gradient(135deg, #ecfdf5 0%, #ccfbf1 100%);
  color: #134e4a;
  min-height: 180px;
  position: relative;
  border: none;
}
.hero-content {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.hero-header { display: flex; flex-direction: column; gap: 4px; }
.hero-label { font-size: 14px; color: rgba(19, 78, 74, 0.6); font-weight: 500; }
.hero-value { display:flex; align-items: baseline; gap: 4px; color: #134e4a; margin-top: 4px; }
.hero-value .num { font-size: 48px; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1; }
.hero-value .unit { font-size: 20px; opacity: 0.8; font-weight: 500; }
.hero-change { display:flex; align-items:center; gap:6px; font-size: 13px; color: #0f766e; margin-top: 4px; font-weight: 500; }
.hero-change .icon { width: 16px; height: 16px; }
.hero-footer { margin-top: 20px; }
.progress-labels { display: flex; justify-content: space-between; align-items: flex-end; margin-bottom: 8px; }
.progress-text { font-size: 14px; font-weight: 600; color: #115e59; }
.goal-text { font-size: 12px; color: rgba(15, 118, 110, 0.7); }
.progress-track { width: 100%; height: 12px; background-color: rgba(255, 255, 255, 0.5); border-radius: 999px; overflow: hidden; backdrop-filter: blur(4px); }
.progress-fill { height: 100%; border-radius: 999px; background: linear-gradient(90deg, #34d399 0%, #fb923c 100%); transition: width 0.5s ease-out; }

.quick-card { grid-column: span 1; display:flex; flex-direction:column; gap: 12px; background:#f1f5f9; min-height: 180px; }
.card-header { display:flex; align-items:center; justify-content:space-between; font-size:16px; color: var(--gray-900); font-weight: 600; margin-bottom: 8px; }
.quick-form { display:flex; align-items:center; gap: 12px; }
.quick-form input { flex:1; min-width: 220px; border:1px solid var(--border); border-radius: 8px; padding: 10px 12px; }
.quick-form select { border:1px solid var(--border); border-radius: 8px; padding: 10px 12px; min-width: 120px; }
.primary-btn { background: #10b981; color:#fff; border:none; border-radius: 8px; padding: 10px 14px; font-weight: 700; flex-shrink: 0; }
.primary-btn:hover { background:#059669; }
.quick-chips { display:flex; gap:8px; flex-wrap: wrap; margin-top: 10px; }
.chip { background:#e5e7eb; color:#111827; border:none; border-radius: 999px; padding:6px 10px; font-size:12px; cursor:pointer; }
.chip:hover { background:#d1d5db; }

.title-icons {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 1.8rem;
}

.page-title {
  margin: 0;
  font-size: 1.8rem;
  font-weight: bold;
}

.carbon-summary {
  text-align: center;
}

.carbon-summary h2 {
  margin: 0 0 10px 0;
  font-size: 1.2rem;
  font-weight: 500;
}

.carbon-value {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 5px;
  margin-bottom: 10px;
}

.value {
  font-size: 2.5rem;
  font-weight: bold;
}

.unit {
  font-size: 1.2rem;
}

.trend {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
}

.trend-icon.down {
  color: #42b983;
  font-weight: bold;
}

.trend-text {
  font-size: 0.9rem;
}


.quick-input-inline {
  display: flex;
  align-items: center;
  gap: 10px;
}
.quick-input-inline input {
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 8px;
  min-width: 320px;
}

/* 页面内容布局 */
.carbon-content {
  display: grid;
  grid-template-columns: 300px 1fr 250px;
  gap: 20px;
  width: 100%;
  box-sizing: border-box;
  align-items: stretch;
  min-height: calc(100vh - 220px);
}

/* 左侧功能导航 */
.left-navigation {
  display: flex;
  flex-direction: column;
  gap: 20px;
  height: 100%;
}

.nav-item {
  background: white;
  border-radius: 15px;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
  padding: 20px;
  box-sizing: border-box;
  cursor: pointer;
  transition: all 0.3s;
}

.nav-item:hover,
.nav-item.active {
  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
  transform: translateY(-2px);
}

.nav-item.active {
  border-left: 4px solid #1a535c;
}

.nav-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 15px;
}

.nav-header h2 {
  margin: 0;
  color: #2c3e50;
  font-size: 1.3rem;
}

.nav-content .status {
  margin: 0 0 15px 0;
  color: #ff6b35;
  font-weight: 500;
}

.history-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.history-item {
  display: flex;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid #eee;
}

.history-item:last-child {
  border-bottom: none;
}

.date {
  color: #6c757d;
}

.carbon {
  font-weight: bold;
  color: #1a535c;
}

.sub-nav {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.sub-item {
  padding: 10px 15px;
  border-radius: 8px;
  background-color: #f8f9fa;
  color: #6c757d;
  transition: all 0.3s;
}

.sub-item:hover,
.sub-item.active {
  background-color: #1a535c;
  color: white;
}

/* 中间主数据区 */
.main-data {
  display: flex;
  flex-direction: column;
  gap: 20px;
  height: 100%;
}

.main-data .data-section:last-child {
  margin-top: auto;
}

.data-section {
  background: white;
  border-radius: 15px;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
  padding: 25px;
  box-sizing: border-box;
  display: none;
}

.data-section.active {
  display: block;
}

.section-header h2 {
  margin: 0 0 20px 0;
  color: #2c3e50;
  font-size: 1.5rem;
}

/* 饼图样式 */
.breakdown-card { grid-column: span 2; }
.composition { display:flex; gap: 12px; align-items: center; justify-content: center; }
.donut { width: 240px; display:flex; align-items:center; justify-content:center; }
.donut-ring { width: 220px; height: 220px; border-radius: 999px; display:flex; align-items:center; justify-content:center; }
.donut-center { width: 120px; height: 120px; border-radius: 999px; background: #ffffff; border:1px solid var(--border); display:flex; flex-direction:column; align-items:center; justify-content:center; box-shadow: 0 0 10px rgba(0,0,0,0.06); }
.donut-total { font-size: 24px; font-weight: 700; color:#111827; font-variant-numeric: tabular-nums; }
.donut-label { font-size: 12px; color:#6b7280; margin-top: 4px; }
.comp-list { flex:0 0 auto; display:flex; flex-direction:column; gap: 4px; max-width: 420px; width: 100%; }
.comp-item { display:flex; align-items:center; justify-content:space-between; padding: 6px 0; border-bottom: 1px solid rgba(229,231,235,0.5); background: transparent; }
.comp-left { display:flex; align-items:center; gap:8px; }
.comp-dot { width:10px; height:10px; border-radius:999px; }
.comp-name { font-size: 13px; color:#374151; }
.comp-right { display:flex; align-items:center; gap:8px; }
.comp-percent { font-size: 12px; color:#6b7280; }
.comp-value { font-size: 14px; font-weight: 600; color:#111827; font-variant-numeric: tabular-nums; }

.pie-chart {
  width: 250px;
  height: 250px;
  border-radius: 50%;
  background: conic-gradient(
    #42b983 0% 42%,
    #ff6b35 42% 72%,
    #1a535c 72% 89%,
    #4ecdc4 89% 100%
  );
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}

.chart-center {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  background-color: white;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

.center-value {
  font-size: 1.8rem;
  font-weight: bold;
  color: #1a535c;
}

.center-label {
  font-size: 0.9rem;
  color: #6c757d;
}

.legend { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 10px; }
.legend-item { display: flex; align-items: center; gap: 6px; font-size: 12px; }
.legend-color { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.legend-color { border: 1px solid #e6e9ec; }

/* 分类详情列表 */
.category-details {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.category-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 15px;
  border-radius: 10px;
  background-color: #f8f9fa;
  transition: all 0.3s;
}

.category-item:hover {
  background-color: #e9f7ef;
}

.category-info {
  display: flex;
  align-items: center;
  gap: 10px;
}

.category-color {
  width: 15px;
  height: 15px;
  border-radius: 50%;
}

.category-name {
  font-weight: 500;
  color: #2c3e50;
}

.category-value {
  display: flex;
  align-items: center;
  gap: 15px;
}

.value {
  font-weight: bold;
  color: #1a535c;
}

.percentage {
  color: #6c757d;
  font-size: 0.9rem;
}

/* 折线图容器 */
.trend-card { grid-column: span 3; }
.header-tools { display:flex; align-items:center; gap: 8px; }
.tool-btn { border:1px solid var(--border); background:#f8fafc; color:#334155; border-radius: 8px; padding:6px 10px; }
.tool-btn.active, .tool-btn:hover { background:#e2e8f0; }
.chart-area { margin-top: 12px; }
.trend-chart { width: 100%; height: 300px; }
.chart-skeleton { height:300px; border-radius:8px; background: linear-gradient(90deg,#f1f5f9 25%,#e2e8f0 37%,#f1f5f9 63%); background-size: 400% 100%; animation: shimmer 1.4s infinite; }

.chart-placeholder {
  background-color: #f8f9fa;
  border-radius: 10px;
  height: 300px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.line-tooltip { position: fixed; background: #fff; border: 1px solid #eee; border-radius: 6px; padding: 6px 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.08); font-size: 12px; color: #2c3e50; }

.line-svg { width: 100%; height: auto; }
.line-legend { display: flex; align-items: center; gap: 8px; margin-top: 8px; font-size: 12px; }
.legend-dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }

.line-chart {
  width: 100%;
  height: 100%;
  background: linear-gradient(transparent 0%, #4ecdc4 50%, transparent 100%);
  position: relative;
}

/* 筛选器 */
.filters {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 15px;
}

.time-filter {
  display: flex;
  gap: 10px;
}

.filter-btn {
  padding: 8px 15px;
  border-radius: 20px;
  background-color: #f8f9fa;
  color: #6c757d;
  border: none;
  cursor: pointer;
  transition: all 0.3s;
}

.filter-btn:hover,
.filter-btn.active {
  background-color: #1a535c;
  color: white;
}

.category-filter select {
  padding: 8px 15px;
  border-radius: 20px;
  border: 1px solid #dee2e6;
  background-color: white;
}

/* 建议卡片 */
.history-card { grid-column: span 1; }
.view-all { font-size: 13px; color: var(--emerald-500); }
.history-body { display:flex; flex-direction:column; gap: 8px; max-height: 300px; overflow-y:auto; overflow-x:hidden; }
.today-tip { color: var(--amber-500); font-size: 13px; padding: 4px 0; }
.history-item { display:grid; grid-template-columns: 120px 1fr 120px; align-items:center; column-gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--border); }
.history-item:last-child { border-bottom: none; }
.history-item .date { color: var(--gray-500); font-size: 13px; font-variant-numeric: tabular-nums; }
.history-item .history-main { display:flex; align-items:center; gap:8px; min-width:0; }
.history-item .value { font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; font-size: 18px; }

.tips-card { grid-column: span 3; }
.swap-btn { display:flex; align-items:center; gap:6px; border:none; background:#f1f5f9; color:#334155; padding:6px 10px; border-radius:8px; }
.swap-btn:disabled { opacity:.6; }
.swap-btn:hover { background:#e2e8f0; }
.swap-icon { width:16px; height:16px; }
.tips-grid { display:grid; grid-template-columns: repeat(3,1fr); gap: 16px; margin-top: 12px; }
.tips-skeleton { height:96px; border-radius:12px; background: linear-gradient(90deg,#f1f5f9 25%,#e2e8f0 37%,#f1f5f9 63%); background-size: 400% 100%; animation: shimmer 1.4s infinite; grid-column: 1 / -1; }
.tip-item { display:flex; gap:12px; background:#f9fafb; border:1px solid var(--border); border-radius:10px; padding:12px; }
.tip-icon-wrap { width:40px; height:40px; border-radius:999px; background:#d1fae5; display:flex; align-items:center; justify-content:center; }
.tip-icon { width:20px; height:20px; color:#059669; }
.tip-title { font-size: 14px; font-weight: 600; color: var(--gray-900); }
.tip-desc { font-size: 12px; color: var(--gray-500); margin-top: 4px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.tip-saving { font-size: 12px; color:#047857; margin-top: 6px; }
.retry-btn { margin-left: 8px; font-size: 12px; color: #334155; background: #f1f5f9; border-radius: 6px; padding: 4px 8px; border: none; }

.suggestion-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
}

.suggestion-card h3 {
  margin: 0 0 10px 0;
  color: #2c3e50;
}

.suggestion-desc {
  color: #6c757d;
  margin-bottom: 20px;
  line-height: 1.5;
}

.roi-progress {
  margin-bottom: 20px;
}

.progress-bar {
  width: 100%;
  height: 10px;
  background-color: #e9ecef;
  border-radius: 5px;
  overflow: hidden;
  margin-bottom: 8px;
}

.progress-fill {
  height: 100%;
  background: linear-gradient(90deg, #42b983, #2a8a64);
  border-radius: 5px;
}

.roi-label {
  font-size: 0.9rem;
  color: #6c757d;
}

.action-btn {
  width: 100%;
  padding: 12px;
  border-radius: 25px;
  background-color: #ff6b35;
  color: white;
  border: none;
  cursor: pointer;
  font-weight: bold;
  transition: all 0.3s;
}

.action-btn:hover {
  background-color: #e55a2b;
  transform: scale(1.02);
}

/* 右侧辅助信息区 */
.right-info {
  display: grid;
  grid-template-rows: auto 1fr;
  gap: 20px;
  height: 100%;
}

.info-card {
  background: white;
  border-radius: 15px;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
  padding: 20px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
}

.info-card h3 {
  margin: 0 0 15px 0;
  color: #2c3e50;
  padding-bottom: 10px;
  border-bottom: 1px solid #eee;
}

.info-header { display: flex; align-items: center; justify-content: space-between; }
.info-tools { display: flex; gap: 8px; }
.small-refresh { border: none; background: #f1f5f9; color: #334155; padding: 6px 10px; border-radius: 8px; cursor: pointer; }
.small-refresh:disabled { opacity: 0.6; cursor: default; }
.small-refresh:hover { background: #e2e8f0; }

.top-behaviors {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.behavior-item {
  display: flex;
  justify-content: space-between;
  padding: 10px 0;
  border-bottom: 1px solid #eee;
}

.behavior-item:last-child {
  border-bottom: none;
}

.behavior-name {
  color: #6c757d;
}

.behavior-name { display: flex; align-items: center; gap: 8px; }
.behavior-dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }

.behavior-value {
  font-weight: bold;
  color: #1a535c;
}

.knowledge-card {
  display: flex;
  align-items: center;
  gap: 16px;
  background: white;
  border-radius: 12px;
  padding: 16px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06);
}

.knowledge-icon {
  font-size: 1.6rem;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #fff7ed;
  color: #ea580c;
  border-radius: 50%;
}

.knowledge-title { margin: 0 0 6px 0; color: #2c3e50; font-weight: 700; }

.knowledge-summary { margin: 0; color: #6c757d; font-size: 0.92rem; line-height: 1.5; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.knowledge-tags { margin-top: 8px; display: flex; gap: 8px; flex-wrap: wrap; }
.knowledge-tags .tag { background: #f1f5f9; color: #334155; border-radius: 999px; padding: 4px 8px; font-size: 12px; }
.knowledge-card + .knowledge-card { margin-top: 12px; }

.community-comparison {
  text-align: center;
}

.comparison-value {
  margin-bottom: 15px;
}

.percent {
  font-size: 2.5rem;
  font-weight: bold;
  color: #42b983;
}

.comparison-text {
  margin: 0 0 20px 0;
  color: #6c757d;
}

.progress-container {
  width: 100%;
  height: 12px;
  background-color: #e9ecef;
  border-radius: 6px;
  overflow: hidden;
}

.progress-container .progress-bar {
  height: 100%;
  background: linear-gradient(90deg, #42b983, #2a8a64);
  border-radius: 6px;
}

/* 快速记录日志模态框 */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.quick-log-modal {
  background: white;
  border-radius: 15px;
  padding: 25px;
  width: 90%;
  max-width: 500px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
  box-sizing: border-box;
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.modal-header h2 {
  margin: 0;
  color: #2c3e50;
}

.close-btn {
  background: none;
  border: none;
  font-size: 1.5rem;
  cursor: pointer;
  color: #6c757d;
  padding: 0;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.close-btn:hover {
  color: #ff6b35;
}

.quick-log-options {
  display: flex;
  flex-direction: column;
  gap: 15px;
  margin-bottom: 25px;
}

.log-option {
  display: flex;
  align-items: center;
  padding: 15px;
  border-radius: 10px;
  background-color: #f8f9fa;
  cursor: pointer;
  transition: all 0.3s;
}

.log-option:hover {
  background-color: #e9f7ef;
  transform: translateY(-2px);
}

.option-icon {
  font-size: 1.5rem;
  margin-right: 15px;
}

.option-text {
  flex: 1;
  font-weight: 500;
  color: #2c3e50;
}

.option-value {
  font-weight: bold;
  color: #42b983;
}

.modal-footer {
  display: flex;
  justify-content: flex-end;
}

.cancel-btn {
  padding: 10px 25px;
  border-radius: 25px;
  background-color: #f8f9fa;
  color: #6c757d;
  border: none;
  cursor: pointer;
  font-weight: 500;
  transition: all 0.3s;
}

.cancel-btn:hover {
  background-color: #e9ecef;
}

/* 响应式设计 */
@keyframes shimmer { 0% { background-position: 100% 0 } 100% { background-position: -100% 0 } }
@media (max-width: 992px) { .dashboard-grid { grid-template-columns: 1fr; } .hero-card { grid-column: auto; } .breakdown-card, .trend-card, .tips-card { grid-column: auto; } }
</style>
